import type { InternalAxiosRequestConfig } from 'axios';
import CryptoJS from 'crypto-js';
import { useAuthStore } from '@/store/modules/auth';
import { getRefreshToken, getToken } from '@/store/modules/auth/shared';
import { localStg, sessionStg } from '@/utils/storage';
import { fetchRefreshToken } from '../api';
import type { RequestInstanceState } from './type';

export function getAuthorization() {
  const token = getToken();
  let Authorization = {};
  if (token && token.tokenName && token.tokenValue) {
    Authorization = {
      [token.tokenName]: `${token.tokenValue}`
    };
  }

  return Authorization;
}

// 处理 API 签名
export function handleSignature(config: InternalAxiosRequestConfig) {
  config.params ||= {};
  config.params.timestamp = `${Date.now()}`;
  config.params.nonce = `${Math.floor(Math.random() * 10000000)}`;
  const keys = Object.keys(config.params).sort();
  const paramArr: string[] = [];
  keys.forEach(key => {
    if (config.params[key]) {
      paramArr.push(`${key}=${config.params[key]}`);
    }
  });

  paramArr.push('key=mYqLkFjPbWzXcRgTvHnDdSaAwEeIoOwU');
  config.params.sign = CryptoJS.MD5(paramArr.join('&')).toString();
}

/** refresh token */
async function handleRefreshToken() {
  const { resetStore } = useAuthStore();

  const rToken = getRefreshToken() || <Api.Auth.LoginToken>{};
  const { error, data } = await fetchRefreshToken(rToken);
  if (!error) {
    if (rToken.rememberMe) {
      localStg.set('token', data);
    } else {
      sessionStg.set('token', data);
    }
    return true;
  }

  await resetStore();

  return false;
}

export async function handleExpiredRequest(state: RequestInstanceState) {
  if (!state.refreshTokenFn) {
    state.refreshTokenFn = handleRefreshToken();
  }

  const success = await state.refreshTokenFn;

  setTimeout(() => {
    state.refreshTokenFn = null;
  }, 1000);

  return success;
}

export function showErrorMsg(state: RequestInstanceState, message: string) {
  if (!state.errMsgStack?.length) {
    state.errMsgStack = [];
  }

  const isExist = state.errMsgStack.includes(message);

  if (!isExist) {
    state.errMsgStack.push(message);

    window.$message?.error({
      message,
      onClose: () => {
        state.errMsgStack = state.errMsgStack.filter(msg => msg !== message);

        setTimeout(() => {
          state.errMsgStack = [];
        }, 5000);
      }
    });
  }
}
